/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.soa.util.tccgl;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.lianzt.commondata.AbstractCommonData;
import com.lianzt.commondata.DataConvertFactory;
import com.lianzt.exception.InstanceDataException;
import com.lianzt.rest.TraffRest;
import com.lianzt.util.DateUtil;
import com.lianzt.util.StringUtil;
import com.soa.exception.GlobalException;
import com.soa.util.SystemUtil;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Random;
import java.util.logging.Level;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import sun.applet.Main;

/**
 *
 * @author zuotai
 */
@Component
public class TccglUtil {

    @Resource(name = "traffRest")
    private TraffRest traffRest;
    public int serialCache = 1000;         //流水号
    private final String BASE_SCOPE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=lianzt#wechat_redirect";       //微信的授权url
    private final String BASE_SERVICE_URL = "http%3a%2f%2fapp.jtgzfw.com%2fkslp%2fwx%2fsnsapi.do%3fservice%3d";      //应用内的授权url，在后面直接跟服务码
    private final Logger log = LoggerFactory.getLogger(TccglUtil.class);
    /**
     * 超时时间
     */
    protected final int TIMEOUT = 10000;


    private final int UPLOAD_TIMEOUT = 20000;        //上传超时时间


    /**
     * 上传照片
     * @param files
     * @throws 上传失败时抛出异常
     */
    public void uploadPic(String date, File... files) {
        if (files == null || files.length < 1) {
            return;
        }
        String url = SystemUtil.getSysConfig("upload_url") + date;
        log.debug("开始上传文件，url={}，{} 个文件", url, files.length);
        PostMethod filePost = null;
        try {
            filePost = new PostMethod(url);
            FilePart[] parts = new FilePart[files.length];
            for (int i = 0; i < files.length; i++) {
                parts[i] = new FilePart(files[i].getName(), files[i]);
            }
            
            filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
            
            HttpClient client = new HttpClient();
            client.getHttpConnectionManager().getParams().setConnectionTimeout(UPLOAD_TIMEOUT);
            int status = client.executeMethod(filePost);
            String res = filePost.getResponseBodyAsString();
            if (status == HttpStatus.SC_OK) {
                // 返回成功
                if (!"success".equals(res.trim())) {
                    throw new GlobalException(306001, res);        //上传失败：!#!
                }
            } else {
                throw new GlobalException(306001, "照片库处理失败");        //上传失败：!#!
            }
        } catch (SocketTimeoutException e) {
            throw new GlobalException(306001, "连接照片库超时", e);        //上传失败：!#!
        } catch (IOException e) {
            throw new GlobalException(306001, "网络异常");
        } finally {
            if (filePost != null) {
                filePost.releaseConnection();
            }
        }
    }

    /**
     * 获取流水号
     * 说明：当要调整为分布式部署时，需要修改此函数，流水号后几位要保存在redis中，每次获取之后都进行加一操作（直接在redis中加1），并在每天凌晨重置。
     * 流水号格式为：A + yyyyMMddHHmmss + N + xxxx； N为服务器节点，xxxx为4位序列号
     *
     * @return
     */
    public String getSerialNum() {
        try {
            if (serialCache >= 9999) {
                serialCache = 1000;
            } else {
                serialCache++;
            }
            return "A" + DateUtil.detaledLshFormat(new Date()) + SystemUtil.getSysConfig("server_node") + serialCache;
        } catch (Exception e) {
            log.error("流水号更新异常 : " + e);
            throw new GlobalException(999995);     //生成流水号异常
        }
    }

    /**
     * 获取授权URL
     *
     * @param url
     * @return
     */
    public String getScopeUrl(String service) {
        return String.format(BASE_SCOPE_URL, SystemUtil.getSysConfig("wx_appid"), (BASE_SERVICE_URL + service));
    }

    /**
     * 把状态字母转为汉字
     *
     * @param zt
     * @return
     */
    public String vehZtToDesc(String zt) {
        if (StringUtil.isNull(zt)) {
            return null;
        }
        StringBuilder desc = new StringBuilder();
        for (int i = 0, len = zt.length(); i < len; i++) {
            if (desc.length() > 0) {
                desc.append(",");
            }
            desc.append(SystemUtil.getColValueDesc("veh.zt", Character.toString(zt.charAt(i))));
        }
        return desc.toString();
    }

    /**
     * 调用traff项目api
     *
     * @param serviceId 服务码
     * @param req 请求报文
     * @return 响应报文
     */
    public AbstractCommonData callTraff(String serviceId, AbstractCommonData req) {
        try {
            log.debug("请求报文: {}", req);
            AbstractCommonData res = traffRest.runService(serviceId, req);
            log.debug("响应报文：{}", res);
            if (!"000000".equals(res.getDataValue("head").getStringValue("response_code"))) {
                String errMsg = res.getDataValue("head").getStringValue("response_code") + '-' + res.getDataValue("head").getStringValue("response_desc");
                throw new GlobalException(130104, errMsg);      //数据支撑平台接口错误：!#!
            } else {
                return res;
            }
        } catch (InstanceDataException e) {
            //响应返回数据解析异常
            log.warn("响应数据转换错误：", e);
            throw new GlobalException(130101, e);        //数据支撑平台响应数据格式错误！
        } catch (SocketTimeoutException e) {
            //超时
            throw new GlobalException(130102, e);        //数据支撑平台响应超时！！
        } catch (IOException e) {
            //其它异常
            throw new GlobalException(130103, e);        //数据支撑平台出现异常！！
        }
    }

    /**
     * 上传微信下载的照片到内网服务器
     *
     * @param filename 文件名
     * @param type 文件类型
     */
    public void Upload(String type, String filename) {
        String targetURL = null;// TODO 指定URL
        //      File targetFile1 = new File("D:\\我的文档\\图片\\gx\\1.jpg");// TODO 指定上传文件
        //      File targetFil2 = new File("D:\\我的文档\\图片\\gx\\2.jpg");// TODO 指定上传文件
        //      File targetFile3 = new File("D:\\我的文档\\图片\\gx\\3.jpg");// TODO 指定上传文件
//        System.out.println(targetFile.isFile());
        targetURL = SystemUtil.getSysConfig("wx_upload_host"); //servleturl
        //获取文件夹路径
        String file = SystemUtil.getSysConfig("media_dir");
        File targetFile1 = null;
        if (type != null && !"".equals(type)) {
            if ("image".equals(type)) {
                targetFile1 = new File(file + "\\" + type + "\\" + filename + ".jpg");
            } else if ("voice".equals(type)) {
                targetFile1 = new File(file + "\\" + type + "\\" + filename + ".mp3");
            }
        }

        // File targetFile1 = new File(file+""+filename+".jpg");
        PostMethod filePost = new PostMethod(targetURL);

        try {
            //通过以下方法可以模拟页面参数提交
            //filePost.setParameter("name", "中文");
            //filePost.setParameter("pass", "1234");
            String time = DateUtil.detaledLshFormat(new Date());
            Part[] parts = {new FilePart("1", targetFile1)};
            filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
            HttpClient client = new HttpClient();
            client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
            System.out.println("开始上传");
            int status = client.executeMethod(filePost);
            System.out.println(filePost.getResponseBodyAsString());
            if (status == HttpStatus.SC_OK) {
                System.out.println("上传成功");
                // 上传成功
            } else {
                System.out.println("上传失败");
                // 上传失败
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            filePost.releaseConnection();
        }
    }

    /**
     * 生成二维码
     *
     * @throws WriterException
     * @throws IOException
     */
    public String createQrcode(String url) {
        String qrcodeFilePath = "";
        Integer filename = null;
        String filepath = SystemUtil.getSysConfig("wx_user_code");
        try {
            int qrcodeWidth = 150;
            int qrcodeHeight = 150;
            String qrcodeFormat = "jpg";
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, qrcodeWidth, qrcodeHeight, hints);
            BufferedImage image = new BufferedImage(qrcodeWidth, qrcodeHeight, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics2D g2 = (Graphics2D) image.getGraphics();
            g2.setBackground(Color.WHITE);
            g2.setPaint(Color.RED);
            
            Random random = new Random();
            filename = random.nextInt();
            File mulu = new File(filepath);
            if (!mulu.exists()) {
                mulu.mkdirs();
            }
            File QrcodeFile = new File(mulu, filename + "." + qrcodeFormat);
            ImageIO.write(image, qrcodeFormat, QrcodeFile);
            MatrixToImageWriter.writeToFile(bitMatrix, qrcodeFormat, QrcodeFile);
            qrcodeFilePath = QrcodeFile.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("生成二维码的地址：{}", qrcodeFilePath);
        return filename.toString();
    }

    /**
     * 生成操作说明
     *
     * @param username 操作人用户名
     * @param hphm 车辆号牌号码
     * @param lczt 流程状态
     */
    public String getczsm(String username, String hphm, String lczt) {
        String cz = SystemUtil.getColValueDesc("wx_kcxx.lczt", lczt);
        hphm = StringUtil.isNull(hphm) ? "非机动车" : hphm;
        String czsm = "【" + username + "】对车辆【豫" + hphm + "】执行了【" + cz + "】";
        return czsm;
    }

    /**
     *
     * @param pushUrl
     * @param json
     * @return
     * @throws IOException
     */
    public String pushJSON(String pushUrl, String json) throws IOException {
        if (StringUtil.isNull(json) || StringUtil.isNull(pushUrl)) {
            return null;
        }
        URL url = null;
        URLConnection con = null;
        BufferedWriter bw = null;
        BufferedReader br = null;

        log.info("push url={}, json={}", pushUrl, json);
        try {
            url = new URL(pushUrl);
            con = url.openConnection();
            /**
             * 然后把连接设为输出模式。URLConnection通常作为输入来使用，比如下载一个Web页。
             * 通过把URLConnection设为输出，你可以把数据向你个Web页传送。下面是如何做：
             */
            con.setDoOutput(true);
            con.setConnectTimeout(20000);
            con.setReadTimeout(20000);
            con.addRequestProperty("Content-Type", "application/json");
            con.addRequestProperty("Content-Length", Integer.toString(json.length()));
            /**
             * 最后，为了得到OutputStream，简单起见，把它约束在Writer并且放入POST信息中，例如： ...
             */
            bw = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), "UTF-8"));
            StringBuilder sb = new StringBuilder();
            sb.append(json);
            bw.write(sb.toString());

            bw.flush();

            String tmpStr;
            sb = new StringBuilder();

            br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
            while ((tmpStr = br.readLine()) != null) {
                sb.append(tmpStr);
            }
            log.info("RETURN url={} res={}", pushUrl, sb);
            return sb.toString();
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (Exception e) {
                    log.warn("关闭连接异常：" + e.toString());
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    log.warn("关闭连接异常：" + e.toString());
                }
            }
        }
    }

    /**
     * 内网接口调用
     *
     * @param abs 要传递的参数
     *
     */
    public String Nwjkdy(AbstractCommonData abs) {
        String url = SystemUtil.getSysConfig("nwjk_url");
        String json = DataConvertFactory.praseNormJson(abs);
        String str = "";
        try {
            str = pushJSON(url, json);
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(TccglUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return str;
    }

//删除文件夹
//param folderPath 文件夹完整绝对路径
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); //删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath.toString();
            java.io.File myFilePath = new java.io.File(filePath);
            myFilePath.delete(); //删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//删除指定文件夹下所有文件
//param path 文件夹完整绝对路径
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);//再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     *
     */
    public void deleteFile(String fileName) {
        File folder = new File(SystemUtil.getSysConfig("media_dir"));
        File[] files = folder.listFiles();
        for (File file : files) {
            if (file.getName().equals(fileName)) {
                file.delete();
            }
        }
    }

    public static void main(String[] args) {
        System.out.println(StringUtil.changeNull(null, "21"));
        System.out.println(StringUtil.changeNull("", ""));
        //TccglUtil t = new TccglUtil();
        // t.Upload("image", "LvlBwGS8gkhjTFNK-mMBu1SItzA8k1E3Vf2P4hQn08LuUtT-earzuzIalQqBe8zd");
        //t.createQrcode("https://www.baidu.com");
        // System.out.print(System.currentTimeMillis()/1000);
    }
}
